#ifndef ZVIEW_CTRL_H
#define ZVIEW_CTRL_H

#include <linux/ioctl.h>
#include <linux/types.h>
#include <stdint.h>

#if defined(__cplusplus)
extern "C" {
#endif

// 版本号信息
#define ZVIEW_CTL_VERSION_MAJOR 1
#define ZVIEW_CTL_VERSION_MINOR 0
#define ZVIEW_CTL_VERSION_REVISION 0

#define ZVIEW_CTL_VERSION_STR  __stringify(ZVIEW_CTL_VERSION_MAJOR) "." __stringify(ZVIEW_CTL_VERSION_MINOR) "." __stringify(ZVIEW_CTL_VERSION_REVISION)
#define ZVIEW_CTL_VERSION_CODE ((ZVIEW_CTL_VERSION_MAJOR << 16) | (ZVIEW_CTL_VERSION_MINOR << 8) | ZVIEW_CTL_VERSION_REVISION)

// PCI 最大Bar数量
#define PCI_MAX_BAR_COUNT 6u

// 设备类型枚举
enum zview_device_type {
    TYPE_PCI,
    TYPE_USB,

    // 添加更多
};

// 中断号
enum zview_interrupt_id {
    INT0 = 0,
    INT1,
    INT2,
    INT3,
    INT4,
    INT5,
    INT6,
    INT7,
    INT8,
    INT9,
    INT10,
    INT11,
    INT12,
    INT13,
    INT14,
    INT15,
    INT16,
    INT17,
    INT18,
    INT19,
    INT20,
    INT21,
    INT22,
    INT23,
    INT24,
    INT25,
    INT26,
    INT27,
    INT28,
    INT29,
    INT30,
    INT31,

    INT_COUNT,
};

// DMA 事务类型
enum zview_dma_type {
    SLAVE_TO_HOST,  //  从 设备 到 主机
    HOST_TO_SLAVE,  //  从 主机 到 设备
};

// 设备信息的结构体类型数量和 zview_device_type 的数量需保持一致
// PCI设备信息
struct pci_device_info {
    uint16_t vendor;
    uint16_t device;

    // 添加其他
};

// USB设备信息
struct usb_device_info {
    uint16_t vendor;
    uint16_t device;

    // 添加其他
};

// 通过IOCTL调用获取设备信息
struct zview_device_info {
    enum zview_device_type dev_type;
    union {
        struct pci_device_info pci;
        struct usb_device_info usb;
    };
};

// 设备内存信息，用于获取可映射的内存
struct zview_device_memory_info {
    uint32_t memory_count;  // 这个数据对于PCI设备来说可能只表示最后一个bar的ID
    uint32_t memory_size[PCI_MAX_BAR_COUNT]; // 数据为0则表示没有可用内存，不为0则表示可以用于映射的最大内存大小
};

// 设备中断信息
struct zview_device_int_table {
    uint32_t interrupt_count; // 中断数量，假定中断编号是连续的
    uint32_t interrupt_trigger_counts[INT_COUNT]; // 中断的触发次数
    uint64_t interrupt_trigger_times[INT_COUNT];  // 中断的最后触发时间
};

// DMA 事务
struct zview_device_dma_transaction {
    enum zview_dma_type dma_type;
    void               *src;    // 源地址
    void               *dst;    // 目标地址
    uint32_t            length; // 长度，单位字节
    int32_t             notify_event_fd;
};

// 中断等待信息
struct zview_device_wait_interrupt {
    enum zview_interrupt_id id;
    uint64_t                timeout;
};

// 中断绑定信息
struct zview_interrupt_bind_info {
    enum zview_interrupt_id             id;
    struct zview_device_dma_transaction transaction;
};


// io读写信息
enum zview_io_data_type
{
    TYPE_UINT8  = 0,
    TYPE_UINT16,
    TYPE_UINT32,
    TYPE_UINT64
};

enum zview_io_rw
{
    ZVIEW_READ  = 0,
    ZVIEW_WRITE
};

struct zview_device_io {
    uint8_t                         bar;
    uint64_t                        offset;
    enum zview_io_data_type         type;
    enum zview_io_rw                dir;
    union  {
        uint8_t                     data8;
        uint16_t                    data16;
        uint32_t                    data32;
        uint64_t                    data64;
    };
};

#define IOC_ZVIEW_MAGIC 'Z'
#define IOC_ZVIEW_GET_DEV_INFO          _IOR(IOC_ZVIEW_MAGIC,  0, struct zview_device_info)
#define IOC_ZVIEW_GET_INT_INFO_TABLE    _IOR(IOC_ZVIEW_MAGIC,  1, struct zview_device_int_table)
#define IOC_ZVIEW_WAIT_INT              _IOR(IOC_ZVIEW_MAGIC,  2, struct zview_device_wait_interrupt)
#define IOC_ZVIEW_DMA_TRANSACTION       _IOWR(IOC_ZVIEW_MAGIC, 3, struct zview_device_dma_transaction)
#define IOC_ZVIEW_CONFIG_INT_BIND       _IOWR(IOC_ZVIEW_MAGIC, 4, struct zview_interrupt_bind_info)
#define IOC_ZVIEW_GET_PHY_MEM_INFO      _IOR(IOC_ZVIEW_MAGIC,  5, struct zview_device_memory_info)


#define IOC_ZVIEW_IO_WR                 _IOWR(IOC_ZVIEW_MAGIC, 6, struct zview_device_io)





#if defined(__cplusplus)
}
#endif

#endif // ZVIEW_CTRL_H